package com.demo.common.ratelimit.interceptor;

import com.demo.common.ratelimit.config.RateLimiterProperties;
import com.demo.common.ratelimit.exception.RateLimitException;
import com.demo.common.ratelimit.utils.HttpUserInfoUtil;
import com.demo.common.ratelimit.utils.IpAddressUtil;
import com.demo.common.ratelimit.utils.ThreadLocalUtil;
import com.demo.common.redis.component.RedisKeys;
import com.demo.common.redis.component.StringRedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 * @Author：DayDayUp
 * @Create：2023/2/6 15:34
 */
@Order(1)
@Slf4j
public class UserWebInterceptor implements HandlerInterceptor {

    @Resource
    private StringRedisUtil stringRedisUtil;
    @Resource
    private RateLimiterProperties rateLimiterProperties;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {

        if (Boolean.TRUE.equals(ThreadLocalUtil.getTlBoolean())) {
            ThreadLocalUtil.removeTlBoolean();
            return true;
        }

        // handler是否为 HandleMethod 实例
        if (handler instanceof HandlerMethod) {

            String username = HttpUserInfoUtil.getSessionUser(request);
            String ip = IpAddressUtil.getIpAddress(request);
            String userAgent = request.getHeader("user-agent");
            if (!StringUtils.hasText(ip) || !StringUtils.hasText(userAgent)) {
                throw new RateLimitException("当前请求错误");
            }

            // ip + user    5s 20次访问
            String userWebKey;
            if (StringUtils.hasText(username)) {
                userWebKey = RedisKeys.userWebLimit(username);
            } else {
                userWebKey = RedisKeys.userWebLimit(ip);
            }

            String userWebValue = stringRedisUtil.get(userWebKey);
            if (Objects.isNull(userWebValue)) {
                stringRedisUtil.set(userWebKey, "1", rateLimiterProperties.getUserWebTime());
            } else {
                int currentCnt = Integer.parseInt(userWebValue) + 1;
                if (currentCnt <= rateLimiterProperties.getUserWebCount()) {
                    long expire = stringRedisUtil.getExpire(userWebKey);
                    if (expire > 0) {
                        stringRedisUtil.set(userWebKey, String.valueOf(currentCnt), expire);
                    }
                } else {
                    throw new RateLimitException("网站访问次数已达上限");
                }
            }
        }
        return true;
    }
}
